package user_interface;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import controller.SimpleController;
import controller.thread_pool_solver.Result;

import model.ProblemData;
import model.SimpleModel;

public class UserInterface extends JFrame implements FBUserInterface {
	private final static long serialVersionUID = 1L;
	// Swing components
	private JPanel instrumentPanel, viewPanel;
	private JMenu fileMenu;
	private JMenuBar menuBar;
	private JTextArea consoleTextArea;
	private JLayeredPane mapPanel;
	private JLabel currentFileLabel;
	private JTextField rpTextField, threadTextField, maxIterationTextField, beginingPopulationTextField;
	private JLabel rpLabel, wLabel, maxIterationLabel, beginingPopulationLabel;
	private JLabel threadLabel;
	private JButton calculateButton, pauseButton;
	// Main data
	private SimpleModel model;
	private SimpleController controller;
	private boolean pause_state = false;
	/**
	 * Constructor.
	 */
	public UserInterface(SimpleController controller, SimpleModel model) {
		super("Genethic alghoritm");
		// initialize window
		setLayout(new GridLayout(1, 1));
		//setResizable(false);
		setSize(1000, 800);
		setLocation(200,200);
		setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				UserInterface.this.controller.shutdown();
			}
		});
		
		// initialize data
		this.model = model;
		this.controller = controller;
		
		// initialize swing components
		create_menu_bar();
		create_instrument_panel();
		create_view_panel();
		
		// build
		setJMenuBar(menuBar);
		
		JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, instrumentPanel, viewPanel);
		split.setResizeWeight(0.1);
		add(split);
		
		setVisible(true);
	}
	
	@Override
	public void setResult(final Result result) {
		if(!SwingUtilities.isEventDispatchThread()) {
			SwingUtilities.invokeLater(new Runnable() {
				@Override
				public void run() {
					setResult(result);
				}
			});
		} else {
			ProblemData data = model.getData();
			mapPanel.removeAll();

			double maxX = 1, maxY = 1;
			for(int i = 0; i < data.x_coord.length; i++) {
				if(data.x_coord[i] > maxX) maxX = data.x_coord[i]; 
				if(data.y_coord[i] > maxY) maxY = data.y_coord[i]; 
			}
			
			Color leader_color = new Color(34, 177, 76);
			Color rival_color = new Color(255, 0, 0);
			Color leader_client_color = new Color(183, 255, 183);
			Color rival_client_color = Color.GRAY;
			
			int size_x = 50;
			int size_y = 25;
			
			for(int i = 0; i < data.x_coord.length; i++) {
				JButton butt = new JButton(Integer.toString(i));
				double x = (data.x_coord[i] / maxX) * (mapPanel.getSize().width - size_x) - size_x / 2;
				double y = mapPanel.getSize().height - (data.y_coord[i] / maxY) * (mapPanel.getSize().height - size_y) - size_y / 2;
				butt.setLocation((int)(x + 0.5), (int)(y + 0.5));
				butt.setSize(size_x, size_y);
				if(result.getX()[i] == 1) {
					mapPanel.add(butt, new Integer(2));
					butt.setBackground(leader_color);
				} else if(result.getY()[i] == 1) {
					mapPanel.add(butt, new Integer(2));
					butt.setBackground(rival_color);
				} else if(result.getZ()[i] == 1){
					mapPanel.add(butt, new Integer(1));
					butt.setBackground(leader_client_color);
				} else {
					mapPanel.add(butt, new Integer(1));
					butt.setBackground(rival_client_color);
				}
			}
			mapPanel.updateUI();
			mapPanel.repaint();
		}
	}
	
	@Override
	public void print2console(String text) {
		consoleTextArea.append(text + "\n");
		consoleTextArea.setCaretPosition(consoleTextArea.getDocument().getLength());
	};
//=============================================================================
//------------------PRIVATE METHODS--------------------------------------------
	private void create_menu_bar() {
		menuBar = new JMenuBar();
		fileMenu = new JMenu("File");
		
		JMenuItem openFileMenu = new JMenuItem("Open");
		openFileMenu.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				JFileChooser fileChooser = new JFileChooser(".");
				Component parent = UserInterface.this;
				if (fileChooser.showOpenDialog(parent) == JFileChooser.APPROVE_OPTION) {
					String fileName = fileChooser.getSelectedFile().getPath();
					currentFileLabel.setText("Please, waiting");
					boolean re = UserInterface.this.model.openFile(fileName);
					if (re) {
						currentFileLabel.setText("File : "
								+ fileChooser.getSelectedFile().getName());
					} else {
						consoleTextArea.append("Can't open file "
								+ fileChooser.getSelectedFile().getName() + "\n");
					}
				}
			}
		});
		fileMenu.add(openFileMenu);

		menuBar.add(fileMenu);
	}
	
	private void create_instrument_panel() {
		instrumentPanel = new JPanel(new GridLayout(1, 1));
		JPanel tmpPanel = new JPanel(new GridBagLayout());
		JScrollPane tmpScroll = new JScrollPane(tmpPanel);
		instrumentPanel.add(tmpScroll);

		// create components
		// File
		currentFileLabel = new JLabel("File : please open file");
		GridBagConstraints gbc = new GridBagConstraints(0,0,  2,1,  1,0,  GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 20, 1),  0,0);
		tmpPanel.add(currentFileLabel, gbc);

		// rp parameters
		rpTextField = new JTextField("5");
		rpLabel = new JLabel("r | p :");
		gbc = new GridBagConstraints(0,1,  1,1,  0,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  0,0);
		tmpPanel.add(rpLabel, gbc);
		gbc = new GridBagConstraints(1,1,  1,1,  1,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  30,0);
		tmpPanel.add(rpTextField, gbc);
		
		// w parameter
		wLabel = new JLabel("Parameter w will equal 1 or taken from the file");
		gbc = new GridBagConstraints(0,2,  2,1,  1,0,  GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 20, 1),  0,0);
		tmpPanel.add(wLabel, gbc);
		
		// thread parameters
		threadLabel = new JLabel("Threads :");
		threadTextField = new JTextField("2");
		//threadTextField.setEditable(false);
		gbc = new GridBagConstraints(0,3,  1,1,  0,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  0,0);
		tmpPanel.add(threadLabel, gbc);
		gbc = new GridBagConstraints(1,3,  1,1,  1,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  30,0);
		tmpPanel.add(threadTextField, gbc);
		
		beginingPopulationLabel = new JLabel("Begining population :");
		beginingPopulationTextField = new JTextField("100");
		gbc = new GridBagConstraints(0,4,  1,1,  0,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  0,0);
		tmpPanel.add(beginingPopulationLabel, gbc);
		gbc = new GridBagConstraints(1,4,  1,1,  1,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  30,0);
		tmpPanel.add(beginingPopulationTextField, gbc);

		maxIterationLabel = new JLabel("Max iteration :");
		maxIterationTextField = new JTextField("100");
		gbc = new GridBagConstraints(0,5,  1,1,  0,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  0,0);
		tmpPanel.add(maxIterationLabel, gbc);
		gbc = new GridBagConstraints(1,5,  1,1,  1,0,  GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(1, 1, 1, 1),  30,0);
		tmpPanel.add(maxIterationTextField, gbc);

		calculateButton = new JButton("Calculate");
		pauseButton = new JButton("Pause");
		gbc = new GridBagConstraints(0,6,  1,1,  1,1,  GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 1, 1),  0,0);
		tmpPanel.add(calculateButton, gbc);
		gbc = new GridBagConstraints(1,6,  1,1,  0,1,  GridBagConstraints.SOUTH, GridBagConstraints.HORIZONTAL, new Insets(1, 1, 1, 1),  0,0);
		tmpPanel.add(pauseButton, gbc);
		pauseButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				pause_state = !pause_state;
				UserInterface.this.controller.pause(pause_state);
				if(pause_state)
					pauseButton.setText("Play");
				else
					pauseButton.setText("Pause");
			}
		});
		calculateButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				// Get r|p parameter
				Integer rp = 5;
				try {
					String pText = rpTextField.getText();
					rp = new Integer(pText);
				} catch (Exception ex) {}				
				rp = UserInterface.this.model.setP(rp);
				rpTextField.setText(rp.toString());
				UserInterface.this.model.setR(rp);
				
				// Get thread count
				Integer thread = 1;
				try {
					String threadText = threadTextField.getText();
					thread = new Integer(threadText);
				} catch (Exception ex) {
					threadTextField.setText(thread.toString());							
				}
				
				// Get max iteration
				Integer maxIteration = 100;
				try {
					String maxIterationText = maxIterationTextField.getText();
					maxIteration = new Integer(maxIterationText);
				} catch (Exception ex) {
					maxIterationTextField.setText(maxIteration.toString());							
				}

				// Get beginning population
				Integer beginningPopulation = 100;
				try {
					String beginingPopulationText = beginingPopulationTextField.getText();
					beginningPopulation = new Integer(beginingPopulationText);
				} catch (Exception ex) {
					beginingPopulationTextField.setText(beginningPopulation.toString());							
				}

				UserInterface.this.controller.calculate(thread, maxIteration, beginningPopulation);
			}
		});				
	}
	
	private void create_view_panel() {
		viewPanel = new JPanel(new GridLayout(1, 1));
		
		consoleTextArea = new JTextArea();
		consoleTextArea.setFont(new Font("Consolas", 1, 12));
		consoleTextArea.setEditable(false);
		JScrollPane consoleScroll = new JScrollPane(consoleTextArea);
		consoleScroll.setAutoscrolls(true);
		
		
		mapPanel = new JLayeredPane();
		JScrollPane mapScroll = new JScrollPane(mapPanel);
		mapScroll.setAutoscrolls(true);
		
		JSplitPane split = new JSplitPane(JSplitPane.VERTICAL_SPLIT, mapScroll, consoleScroll);
		split.setResizeWeight(0.7);
		viewPanel.add(split);
	}
}
